/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_components/zhiqim_manager.htm
 *
 * Zhiqim Manager is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.manager.presenter;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.zhiqim.httpd.HttpRequest;
import org.zhiqim.httpd.context.ZmlContexts;
import org.zhiqim.httpd.context.annotation.AnIntercept;
import org.zhiqim.kernel.annotation.AnAlias;
import org.zhiqim.kernel.constants.CodeConstants;
import org.zhiqim.kernel.model.maps.HashMapSO;
import org.zhiqim.kernel.model.maps.MapSO;
import org.zhiqim.kernel.paging.PageBuilder;
import org.zhiqim.kernel.paging.PageResult;
import org.zhiqim.kernel.util.Linux;
import org.zhiqim.kernel.util.Systems;

/**
 * 进程状态查询控制器
 *
 * @version v1.0.0 @author liuhu 2018-9-6 新建与整理
 */
@AnAlias("ZmrProcessPresenter")
@AnIntercept("chkZmrLogin")
public class ZmrProcessPresenter implements CodeConstants
{
    /**
     * 获取进程信息
     * 
     * @param request       请求
     * @throws Exception    异常
     */
    public static void doShowProcessInfo(HttpRequest request) throws Exception
    {
        if (Systems.isWindows())
        {
            request.setResponseError("暂不支持Windows查询进程信息");
            return;
        }
        
        int pid = Systems.getPid();
        String shell = new StringBuilder("top -H -p ").append(pid).append(" -n 1 -b").toString();
        String data = Linux.shell(shell, _UTF_8_);
        
        List<String> list = findProcessInfo(data);
        List<List<String>> threadList = findThreadList(data);
        
        int page = request.getParameterInt("page", 1);
        PageResult<List<String>> result = PageBuilder.pageResult(page, 15, threadList);
        MapSO variable = new HashMapSO();
        variable.put("pid", pid);
        variable.put("list", list);
        variable.put("result", result);
        
        String responseText = ZmlContexts.parseZmlPath(request, "/zview/zhiqim_manager/presenter/processInfo.zml", variable);
        request.setResponseResult(responseText);
    }
    
    /**
     * 正则表达式获取线程列表
     * 
     * @param data          进程字符串
     * @return              线程列表
     */
    public static List<List<String>> findThreadList(String data)
    {
        List<List<String>> list = new ArrayList<List<String>>(); 
        Pattern pattern = Pattern.compile("(\\d+)\\s+(\\w+)\\s+(\\d)+\\s+(\\d+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)");
        Matcher matcher = pattern.matcher(data);
        while(matcher.find())
        {
            List<String> stringList = new ArrayList<String>();
            stringList.add(matcher.group(1));
            stringList.add(matcher.group(2));
            stringList.add(matcher.group(3));
            stringList.add(matcher.group(4));
            stringList.add(matcher.group(5));
            stringList.add(matcher.group(6));
            stringList.add(matcher.group(7));
            stringList.add(matcher.group(8));
            stringList.add(matcher.group(9));
            stringList.add(matcher.group(10));
            stringList.add(matcher.group(11));
            stringList.add(matcher.group(12));
            list.add(stringList);
        }
        return list;
    }
    
    /**
     * 正则表达式获取进程信息前五行
     * 
     * @param data          进程字符串
     * @return              进程信息表
     */
    public static List<String> findProcessInfo(String data)
    {
        List<String> list = new ArrayList<String>();
        Pattern pattern = Pattern.compile("\\S.+\\n");
        Matcher matcher = pattern.matcher(data);
        int i = 0;
        while(matcher.find())
        {
            if(i++ == 5)
                break;
            
            list.add(matcher.group());
        }
        return list;
    }
    
    /**
     * 正则表达式获取线程堆栈信息
     * 
     * @param data          进程字符串
     * @return              进程堆栈表
     */
    public static List<String> findThreadStack(String data)
    {
        List<String> list = new ArrayList<String>();
        Pattern pattern = Pattern.compile("\\\"([\\s\\S]+?\"[\\s\\S]+?)(?=\\\"|JNI)");
        Matcher matcher = pattern.matcher(data);
        while(matcher.find())
        {
            list.add(matcher.group());
        }
        return list;
    }
    
    /**
     * 正则表达式获得线程PID
     * 
     * @param result        进程字符串
     * @return              线程PID
     */
    public static String findPid(String result)
    {
        StringBuilder str = new StringBuilder();
        Pattern pattern = Pattern.compile("nid=0x(\\w+)");
        Matcher matcher = pattern.matcher(result);
        while(matcher.find())
        {
            str.append(matcher.group(1));
        }
        return str.toString();
    }
}
